#!/usr/bin/perl -c

package PIPL::File::Stat;
use 5.006;
our $VERSION = '0.01';

=head1 NAME

PIPL::File::Stat - status info for a file

=head1 SYNOPSIS

  use PIPL::File::Stat;
  $fh = new PIPL::IO::File file=>'/etc/pi/main.yml';
  $st = new PIPL::File::Stat file=>$fh;
  print "Size: ", $st->size, "\n";  # named field
  print "Size: ". $st->[7]; "\n";   # numbered field

=head1 DESCRIPTION

This class returns status info for a file.  It is the OO-style version of
stat function.

=cut


use Moose;


has 'file'    => ( is => 'ro', weak_ref => 1 );
has 'dev'     => ( is => 'ro' );
has 'ino'     => ( is => 'ro' );
has 'mode'    => ( is => 'ro' );
has 'nlink'   => ( is => 'ro' );
has 'uid'     => ( is => 'ro' );
has 'gid'     => ( is => 'ro' );
has 'rdev'    => ( is => 'ro' );
has 'size'    => ( is => 'ro' );
has 'atime'   => ( is => 'ro' );
has 'mtime'   => ( is => 'ro' );
has 'ctime'   => ( is => 'ro' );
has 'blksize' => ( is => 'ro' );
has 'blocks'  => ( is => 'ro' );


__PACKAGE__->meta->make_immutable();


use Exception::Base
    'Exception::Runtime'  => { isa => 'Exception::Base' },
    'Exception::BadValue' => { isa => 'Exception::Runtime' },
    'Exception::IO'       => { isa => 'Exception::System' };


use overload '@{}' => \&deref_array,
             fallback=>1;


# Exporter
use Exporter 'import';
our @EXPORT_OK = qw<stat>;


# Constructor
sub BUILD {
    my ($self, $params) = @_;

    $self->stat($self->file) if defined $self->file;
}


# Method or function
sub stat (;$) {
    # called as function
    return @{ __PACKAGE__->new(file => do { my $file = shift; defined $file ? $file : $_ }) }
        if not ref $_[0] and $_[0] ne __PACKAGE__
            or ref $_[0] and not UNIVERSAL::isa($_[0], __PACKAGE__);

    my $self = shift;
    my $file = shift;
    $file = $_ if not defined $file;

    # called as static method
    if (not ref $self) {
        my $st = $self->new(file => $file);
        return wantarray ? @{ $st } : $st;
    }

    throw Exception::BadValue
          message => 'Usage: ' . __PACKAGE__ . '->stat(FILE)'
        if @_ > 1;

    my %stat;
    @{%$self}{qw<dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks>}
        = CORE::stat $file
        or throw Exception::IO
                 message => 'Cannot stat';

    return $self;
}


# Array dereference
sub deref_array {
    my $self = shift;
    return [ @{%$self}{qw<dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks>} ];
}


1;


=head1 BASE CLASSES

=over 2

=item *

L<Moose::Base>

=back

=head1 IMPORTS

=over

=item use PIPL::File::Stat 'stat';

Imports B<stat> function.

=back

=head1 FIELDS

=over

=item file (ro, weak_ref)

Contains the file for check.  The field can hold file name or file handler.

=item dev (ro)

=item ino (ro)

=item mode (ro)

=item nlink (ro)

=item uid (ro)

=item gid (ro)

=item rdev (ro)

=item size (ro)

=item atime (ro)

=item mtime (ro)

=item ctime (ro)

=item blksize (ro)

=item blocks (ro)

Contains the parameter returned by B<stat> core function.

=back

=head1 CONSTRUCTORS

=over

=item new

Creates the stat object and calls B<stat> method if the I<file> field is
defined.

The object is dereferenced in array context to the array reference which
contains the same values as core B<stat> function output.

  $st = new PIPL::File::Stat file=>'/etc/passwd';
  print "Size: $st->size\n";  # object's field
  print "Size: $st->[7]\n";     # array dereference

=item PIPL::File::Stat->stat(I<file>)

Creates the stat object and calls stat on given I<file>. It returns the object
reference.

  $st = PIPL::File::Stat->stat('/etc/passwd');
  print "Size: ", $st->size, "\n";

=back

=head1 METHODS

=over

=item $st->stat([I<file>])

Calls stat on given I<file> or the file which has beed set with B<new>
constructor. It returns the object reference.

  $st = new PIPL::File::Stat;
  print "Size: ", $st->stat('/etc/passwd')->{size}, "\n";

=back

=head1 FUNCTIONS

=over

=item stat([I<file>])

Calls stat on given I<file>.  If the I<file> is undefined, the <$_> variable
is used instead.

If it is called as function or static method in array context, it returns an
array with the same values as for output of core B<stat> function.

  use PIPL::File::Stat 'stat';
  @st = stat '/etc/passwd';
  print "Size: $st[7]\n";

=back

=head1 SEE ALSO

L<Exception::Base>, L<perlfunc>, L<File::stat>.

=head1 AUTHORS

Piotr Roszatycki E<lt>dexter@debian.orgE<gt>

=head1 COPYRIGHT

Copyright 2007 by Piotr Roszatycki E<lt>dexter@debian.orgE<gt>.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>
